﻿using System;
using System.IO;
using System.Data;
using System.Windows;
using System.Collections;
using System.Windows.Input;
using System.ComponentModel;
using System.Windows.Controls;
using Sinacor.Infra.UI.Common;
using Sinacor.Infra.UI.Controls;
using Sinacor.Infra.UI.Controls.SmartClient;
using System.Collections.Generic;
using Sinacor.Infra.UI.Controls.SmartClient.Validation;
using Sinacor.UI.Bovespa.Ordens.View.SmartClient;
using Sinacor.UI.Bovespa.Clientes.View.SmartClient;
using System.Windows.Threading;
using System.Linq;
using Sinacor.UI.Bovespa.ManutencaoOrdens.Presenter;

namespace Sinacor.UI.Bovespa.ManutencaoOrdens.View.SmartClient
{
    public partial class ManutencaoOrdens : SinacorWindow, IManutencaoOrdens
    {
        #region Event Handlers

        private void CboFormularioMercado_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            TrocarMercado();
        }

        private void CboFormularioOperador_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            TrocarOperador();
        }

        private void CboFormularioTipoOrdem_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            TrocarTipo();
        }

        private void CboFormularioBolsa_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            TrocarBolsa();
        }

        private void TxtFormularioApelidoCliente_LostFocus(object sender, RoutedEventArgs e)
        {
            PresenterManutencaoOrdens.ConfigurarCliente();
        }

        private void BtnCancelarFormulario_Click(object sender, RoutedEventArgs e)
        {
            CancelarFormulario();
        }

        private void btnSalvarFormulario_Click(object sender, RoutedEventArgs e)
        {
            SalvarFormulario();
        }

        private void CboFormularioMsgObservacoes_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            AlterarObservacao();
        }

        private void TxtFormularioQuantidade_LostFocus(object sender, RoutedEventArgs e)
        {
            PresenterManutencaoOrdens.RecalcularValorOrdem();
        }

        private void BtnFormularioPreBoleto_Click(object sender, RoutedEventArgs e)
        {
            PesquisarPreBoletoFormulario();
        }

        private void BtnFormularioAtivo_Click(object sender, RoutedEventArgs e)
        {
            PesquisarAtivoFormulario();
        }

        private void BtnFormularioCliente_Click(object sender, RoutedEventArgs e)
        {
            PesquisarClienteFormulario();
        }

        private void TxtFormularioObservacao_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            TxtFormularioObservacao.Focus();
            TxtFormularioObservacao.IsVisibleChanged -= TxtFormularioObservacao_IsVisibleChanged;
        }

        private void TxtFormularioApelidoCliente_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            TxtFormularioApelidoCliente.Focus();
            TxtFormularioApelidoCliente.IsVisibleChanged -= TxtFormularioApelidoCliente_IsVisibleChanged;
        }

        #endregion

        #region Métodos Privados

        #region Pesquisas

        private void PesquisarClienteFormulario()
        {
            Clientes.Model.PesquisaCliente filtroPesq = new Sinacor.UI.Bovespa.Clientes.Model.PesquisaCliente()
            {
                Apelido = TxtFormularioApelidoCliente.Text
            };

            PesquisaClientes pesquisaClientes = new PesquisaClientes();

            pesquisaClientes.CarregaParametros(Sinacor.UI.Bovespa.Clientes.Model.Enum.JanelaChamada.ManutencaoOrdens, filtroPesq);
            pesquisaClientes.Owner = this;
            pesquisaClientes.SetMenuHeader("Bovespa.Ordens.Label.ManutencaoOrdens");
            pesquisaClientes.ShowDialog();

            if (pesquisaClientes.PesquisaClienteModel.Codigo > 0)
            {
                PresenterManutencaoOrdens.OrdemAtual.ApelidoCliente = pesquisaClientes.PesquisaClienteModel.Apelido;

                if (pesquisaClientes.PesquisaClienteModel.DigitoVerificador.HasValue)
                    PresenterManutencaoOrdens.OrdemAtual.DigitoCliente = (Int16?)pesquisaClientes.PesquisaClienteModel.DigitoVerificador.Value;
                else
                    PresenterManutencaoOrdens.OrdemAtual.DigitoCliente = null;

                TxtFormularioApelidoCliente.UpdateTarget(SinacorTextBox.TextProperty);
                TxtFormularioDigitoCliente.UpdateTarget(SinacorInt32TextBox.ValueProperty);

                PresenterManutencaoOrdens.ObterCliente(PresenterManutencaoOrdens.OrdemAtual.ApelidoCliente);
                PresenterManutencaoOrdens.ConfigurarCliente();
            }
        }

        private void PesquisarAtivoFormulario()
        {
            Ordens.Model.Titulo modelTitulo = new Ordens.Model.Titulo();
            PesquisaTitulo pesquisaTitulo = new PesquisaTitulo();

            modelTitulo.Codigo = TxtFormularioAtivo.Text;
            modelTitulo.Mercado = null;
            modelTitulo.DataPregao = DtpFormularioDataOrdem.Value;

            pesquisaTitulo.CarregarParametros(modelTitulo, null);
            pesquisaTitulo.Owner = this;
            pesquisaTitulo.SetMenuHeader("Bovespa.Ordens.Label.ManutencaoOrdens");
            pesquisaTitulo.ShowDialog();

            if (pesquisaTitulo.TituloEscolhido != null)
            {
                PresenterManutencaoOrdens.OrdemAtual.Ativo = pesquisaTitulo.TituloEscolhido.Codigo;
                TxtFormularioAtivo.UpdateTarget(SinacorTextBox.TextProperty);
                PresenterManutencaoOrdens.ObterTitulo(PresenterManutencaoOrdens.OrdemAtual.Ativo);
                PresenterManutencaoOrdens.ConfigurarTitulo();
                PresenterManutencaoOrdens.RecalcularValorOrdem();
            }
        }

        private void PesquisarPreBoletoFormulario()
        {
            Model.ChaveOrdem ordem = null;
            CasamentoPreBoletos casamentoPreBoletos = null;

            if (PresenterManutencaoOrdens.ValidarOrdemPreBoleto())
            {
                ordem = new Model.ChaveOrdem
                {
                    NumeroOrdem = PresenterManutencaoOrdens.OrdemAtual.NumeroOrdem == null ? 0 : Convert.ToInt32(PresenterManutencaoOrdens.OrdemAtual.NumeroOrdem),
                    NumeroOrdemSubSequencia = PresenterManutencaoOrdens.OrdemAtual.NumeroOrdemSubSequencia == null ? 0 : Convert.ToInt32(PresenterManutencaoOrdens.OrdemAtual.NumeroOrdemSubSequencia),
                    DataOrdem = PresenterManutencaoOrdens.OrdemAtual.DataOrdem
                };

                casamentoPreBoletos = new CasamentoPreBoletos(ordem);
                casamentoPreBoletos.SetMenuHeader("Bovespa.Ordens.Label.ManutencaoOrdens");
                casamentoPreBoletos.Owner = this;
                casamentoPreBoletos.ShowDialog();
            }
        }

        #endregion

        #region Incluir

        private void IncluirModoFormulario()
        {
            PresenterManutencaoOrdens.ModoUtilizado = Model.Enum.ModoTela.Formulario;
            PresenterManutencaoOrdens.Estado = Model.Enum.EstadoTela.Inclusao;

            HabilitarEdicaoPainel(true);

            PresenterManutencaoOrdens.OrdemAtual = null;
            PresenterManutencaoOrdens.OrdemAtual = new Model.Ordem();

            PresenterManutencaoOrdens.ConfigurarManutencaoUnitaria();
        }

        #endregion

        #region Alterar

        private void InicializarTelaModoFormularioEdicao()
        {
            //Desassocia o SelectionChanged do grid pois o SelectedItem
            //será manipulado manualmente.
            dtgOrdens.SelectionChanged -= dtgOrdens_SelectionChanged;

            tabControlPrincipal.SelectedValue = tabOrdens;

            //Atribuir dados da ordem que será alterada para o filtro de pesquisa
            this.PresenterManutencaoOrdens.FiltroOrdens.Numero = _parametroOrdem.NumeroOrdem;
            this.PresenterManutencaoOrdens.FiltroOrdens.DataPregao = _parametroOrdem.DataOrdem;
            _parametroOrdem = null;

            //Consultar a ordem que foi passada como parâmetro de entrada
            this.PresenterManutencaoOrdens.ConsultarOrdens();

            //Apresenta o formulário para edição da ordem, com a ordem pesquisada com os parametros recebidos no construtor
            dtgOrdens.SelectedIndex = 0;
            PresenterManutencaoOrdens.OrdemAtual = (Model.Ordem)dtgOrdens.SelectedItem;
            AlterarModoFormulario();

            //Reassocia o SelectionChanged do grid através do Dispatcher (com prioridade ApplicationIdle0
            //para evitar que o evento seja disparado logo após o carregamento da tela e cause um fluxo errôneo
            //aonde a PresenterManutencaoOrdens.OrdemAtual é recriada e perde o binding junto ao formulário.
            this.Dispatcher.Invoke((Action)delegate()
            {
                dtgOrdens.SelectionChanged += new SelectionChangedEventHandler(dtgOrdens_SelectionChanged);
            },
            System.Windows.Threading.DispatcherPriority.ApplicationIdle);
        }

        private void AlterarModoFormulario()
        {
            PresenterManutencaoOrdens.ModoUtilizado = Model.Enum.ModoTela.Formulario;
            PresenterManutencaoOrdens.Estado = Model.Enum.EstadoTela.Alteracao;

            HabilitarEdicaoPainel(true);

            if (dtgOrdens.SelectedItems.Count == 1)
            {
                PresenterManutencaoOrdens.OrdemAtual = (Model.Ordem)Infra.Common.Serialization.CloneHelper.Clone(PresenterManutencaoOrdens.OrdemAtual);

                PresenterManutencaoOrdens.ConfigurarManutencaoUnitaria();
            }
            else
            {
                ConfigurarFormularioThreeState(true);

                PresenterManutencaoOrdens.ConfigurarAlteracaoLote(new ModelCollection<Model.Ordem>(dtgOrdens.SelectedItems));
            }
        }

        #endregion

        #region Salvar

        /// <summary>
        /// Salvar as informações digitadas no formulário
        /// </summary>
        private void SalvarFormulario()
        {
            this.ClearServiceErrors();

            //Força o binding
            this.MoveFocus(new System.Windows.Input.TraversalRequest(FocusNavigationDirection.Next));
            this.MoveFocus(new System.Windows.Input.TraversalRequest(FocusNavigationDirection.Previous));

            if (PresenterManutencaoOrdens.Estado == Model.Enum.EstadoTela.Inclusao)
            {
                SalvarInsercao();
            }
            else if (dtgOrdens.SelectedItems.Count == 1)
            {
                SalvarAlteracao();
            }
            else
            {
                SalvarAlteracaoLote();
            }

            if (!this.HasErrors)
            {
                HabilitarEdicaoPainel(false);

                PresenterManutencaoOrdens.Estado = Model.Enum.EstadoTela.Leitura;

                ResetarEstadoCampos();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        private void SalvarInsercao()
        {
            int index;

            if (RbtFormularioNaturezaCompra.IsEnabled
                && RbtFormularioNaturezaVenda.IsEnabled
                && ((!RbtFormularioNaturezaCompra.IsChecked.HasValue
                      && !RbtFormularioNaturezaVenda.IsChecked.HasValue)
                    || (!RbtFormularioNaturezaCompra.IsChecked.Value
                        && !RbtFormularioNaturezaVenda.IsChecked.Value)))
            {
                this.ShowError("Bovespa.ManutencaoOrdens.Message.NaturezaOperacaoObrigatorio");
            }

            if (!this.HasErrors)
            {
                DefinirEstadoNaturezaOperacao();

                PresenterManutencaoOrdens.OrdemAtual.ClearErrors();
                PresenterManutencaoOrdens.Ordens.Add(PresenterManutencaoOrdens.OrdemAtual);
                index = PresenterManutencaoOrdens.Ordens.Count - 1;

                AtualizarOrdens();

                dtgOrdens.SelectedItem = PresenterManutencaoOrdens.Ordens[index];
            }
        }

        /// <summary>
        /// Salvar as alterações realizadas em uma determinada ordem via formulário
        /// </summary>
        private void SalvarAlteracao()
        {
            int index;

            if (RbtFormularioNaturezaCompra.IsEnabled
                && RbtFormularioNaturezaVenda.IsEnabled
                && ((!RbtFormularioNaturezaCompra.IsChecked.HasValue
                      && !RbtFormularioNaturezaVenda.IsChecked.HasValue)
                    || (!RbtFormularioNaturezaCompra.IsChecked.Value
                        && !RbtFormularioNaturezaVenda.IsChecked.Value)))
            {
                this.ShowError("Bovespa.ManutencaoOrdens.Message.NaturezaOperacaoObrigatorio");
            }

            if (!this.HasErrors)
            {
                DefinirEstadoNaturezaOperacao();

                PresenterManutencaoOrdens.OrdemAtual.ClearErrors();
                index = PresenterManutencaoOrdens.Ordens.IndexOf((Model.Ordem)dtgOrdens.SelectedItem);
                PresenterManutencaoOrdens.Ordens[index] = PresenterManutencaoOrdens.OrdemAtual;

                //Obtem saldo negociavel
                PresenterManutencaoOrdens.ObterSaldoNegociavel(PresenterManutencaoOrdens.OrdemAtual, Model.Enum.NaturezaOperacao.Venda);

                AtualizarOrdens();

                dtgOrdens.SelectedItem = PresenterManutencaoOrdens.Ordens[index];

                PresenterManutencaoOrdens.IncluirJustificativa(PresenterManutencaoOrdens.Ordens[index]);
            }
        }

        /// <summary>
        /// Salvar as alterações em lote realizadas nas ordens via formulário
        /// </summary>
        private void SalvarAlteracaoLote()
        {
            List<int> indexes = new List<int>();

            if (!this.HasErrors)
            {
                DefinirEstadoNaturezaOperacao();

                foreach (Model.Ordem ordem in dtgOrdens.SelectedItems)
                {
                    indexes.Add(PresenterManutencaoOrdens.Ordens.IndexOf(ordem));
                }

                //Força o Update das models envolvidas na edição em Lote
                //Deve ser feito antes da chamada do método AplicarAlteracaoLote
                //Se feito depois acaba alterando a model, mas a modificação não entra como Updated
                //o que gera erro no fluxo da tela ao tentar cancelar uma model que foi editada em lote
                /*==============================================================================================*/
                PresenterManutencaoOrdens.OrdensAtuais.Clear();

                foreach (int index in indexes)
                {
                    PresenterManutencaoOrdens.Ordens[index].ClearErrors();
                    PresenterManutencaoOrdens.Ordens[index] = (Model.Ordem)Infra.Common.Serialization.CloneHelper.Clone(PresenterManutencaoOrdens.Ordens[index]);
                    PresenterManutencaoOrdens.OrdensAtuais.Add(PresenterManutencaoOrdens.Ordens[index]);
                }
                /*==============================================================================================*/

                PresenterManutencaoOrdens.AplicarAlteracaoLote();

                AtualizarOrdens();

                foreach (int index in indexes)
                {
                    dtgOrdens.SelectedItems.Add(PresenterManutencaoOrdens.Ordens[index]);
                    PresenterManutencaoOrdens.IncluirJustificativa(PresenterManutencaoOrdens.Ordens[index]);
                }
            }
        }

        #endregion

        #region Cancelar

        /// <summary>
        /// Cancela as alterações realizadas via formulário
        /// </summary>
        private void CancelarFormulario()
        {
            this.ClearServiceErrors();

            PresenterManutencaoOrdens.Estado = Model.Enum.EstadoTela.Leitura;

            HabilitarEdicaoPainel(false);

            PresenterManutencaoOrdens.OrdemAtual = CurrentModel;
            AtualizarFormulario();

            PresenterManutencaoOrdens.VerificarOrdemFinanciamentoPOP();

            ResetarEstadoCampos();
        }

        #endregion

        private void ConfigurarFormularioThreeState(bool habilita)
        {
            ChkFormularioDesprezarSaldo.IsThreeState = habilita;
            ChkFormularioDiscricionaria.IsThreeState = habilita;
            ChkFormularioIndicadorOrdemAdmConcorrente.IsThreeState = habilita;
            ChkFormularioPessoaVinculada.IsThreeState = habilita;
        }

        private void TrocarMercado()
        {
            if (CboFormularioTipoMercado.SelectedItem != null)
                PresenterManutencaoOrdens.ConfigurarMercado(((EnumWrapper<Model.Enum.TipoMercado>)CboFormularioTipoMercado.SelectedItem).Value);
        }

        private void TrocarOperador()
        {
            if (CboFormularioOperador.SelectedItem != null)
                PresenterManutencaoOrdens.OrdemAtual.LoginOperador = ((Model.Operador)CboFormularioOperador.SelectedItem).LoginOperador;
            else if (PresenterManutencaoOrdens.OrdemAtual != null)
                PresenterManutencaoOrdens.OrdemAtual.LoginOperador = null;
        }

        private void TrocarTipo()
        {
            if (CboFormularioTipoOrdem.SelectedItem != null)
                PresenterManutencaoOrdens.ConfigurarTipoOrdem(((EnumWrapper<Model.Enum.TipoOrdem>)CboFormularioTipoOrdem.SelectedItem).Value);
        }

        private void TrocarBolsa()
        {
            if (CboFormularioBolsa.SelectedItem != null)
                PresenterManutencaoOrdens.OrdemAtual.NomeBolsa = ((Model.Bolsa)CboFormularioBolsa.SelectedItem).Descricao;
            else if (PresenterManutencaoOrdens.OrdemAtual != null)
                PresenterManutencaoOrdens.OrdemAtual.NomeBolsa = null;
        }

        private void HabilitarEdicaoPainel(bool habilita)
        {
            if (habilita)
            {
                ExpGridOrdens.Visibility = Visibility.Collapsed;
                ExpFormularioOrdens.Visibility = Visibility.Visible;
            }
            else
            {
                ExpGridOrdens.Visibility = Visibility.Visible;
                ExpFormularioOrdens.Visibility = Visibility.Collapsed;
                AtualizarOrdens();
            }
        }

        /// <summary>
        /// Armazena a natureza operação que foi definida no radio button e não possui binding
        /// </summary>
        private void DefinirEstadoNaturezaOperacao()
        {
            if (RbtFormularioNaturezaCompra.IsChecked.HasValue
                && RbtFormularioNaturezaCompra.IsChecked.Value)
                PresenterManutencaoOrdens.OrdemAtual.NaturezaOperacao = Model.Enum.NaturezaOperacao.Compra;
            else if (RbtFormularioNaturezaVenda.IsChecked.HasValue
                && RbtFormularioNaturezaVenda.IsChecked.Value)
                PresenterManutencaoOrdens.OrdemAtual.NaturezaOperacao = Model.Enum.NaturezaOperacao.Venda;
            else
                PresenterManutencaoOrdens.OrdemAtual.NaturezaOperacao = null;
        }

        private void AlterarObservacao()
        {
            if (CboFormularioMsgObservacoes.SelectedItem != null)
                this.CurrentModel.Observacao = String.Concat(this.CurrentModel.Observacao,
                                                             ((Model.Mensagem)CboFormularioMsgObservacoes.SelectedItem).Descricao);
        }

        private void AtribuirFocoCampoObservacao()
        {
            if (TxtFormularioObservacao.IsVisible)
            {
                TxtFormularioObservacao.Focus();
            }
            else
            {
                //Correção de problema:
                //o comando de foco não funciona se o controle não estiver com a propriedade Is Visible
                //e o foco acaba se perdendo na tela
                TxtFormularioObservacao.IsVisibleChanged += new DependencyPropertyChangedEventHandler(TxtFormularioObservacao_IsVisibleChanged);
            }
        }

        #endregion
    }
}
